/**
 * @Author: 490912587@qq.com
 * @Description:
 * @File:  Captcha
 * @Version: 1.0.0
 * @Date: 2021/12/8 11:11
 */

package tool

import (
	"encoding/json"
	"errors"
	"github.com/wenlng/go-captcha/captcha"
	"os"
	"strconv"
	"strings"
)

func GetCaptcha() Captcha {
	capt := captcha.GetCaptcha()
	path, _ := os.Getwd()
	// ====================================================
	// Method: SetBackground(color []string);
	// Desc: 设置验证码背景图
	// ====================================================
	capt.SetBackground([]string{
		path + "/public/upload/captcha/images/1.jpg",
		path + "/public/upload/captcha/images/2.jpg",
		path + "/public/upload/captcha/images/3.jpg",
		path + "/public/upload/captcha/images/4.jpg",
		path + "/public/upload/captcha/images/5.jpg",
	})
	// ====================================================
	// Method: SetFont(fonts []string);
	// Desc: 设置验证码字体
	// ====================================================
	capt.SetFont([]string{
		path + "/public/upload/captcha/fonts/fzshengsksjw_cu.ttf",
		path + "/public/upload/captcha/fonts/fzssksxl.ttf",
		path + "/public/upload/captcha/fonts/hyrunyuan.ttf",
	})
	// ====================================================
	// Method: SetImageSize(size *Size);
	// Desc: 设置验证码主图的尺寸
	// ====================================================
	capt.SetImageSize(&captcha.Size{Width: 300, Height: 300})
	// ====================================================
	// Method: SetThumbSize(size *Size);
	// Desc: 设置验证码缩略图的尺寸
	// ====================================================
	capt.SetThumbSize(&captcha.Size{Width: 150, Height: 40})
	// ====================================================
	// Method: SetFontDPI(val int);
	// Desc: 设置验证码字体的随机DPI，最好是72
	// ====================================================
	capt.SetFontDPI(72)
	// ====================================================
	// Method: SetTextRangLen(val *captcha.RangeVal);
	// Desc: 设置验证码文本总和的随机长度范围
	// ====================================================
	capt.SetTextRangLen(&captcha.RangeVal{Min: 6, Max: 7})
	// ====================================================
	// Method: SetRangFontSize(val *captcha.RangeVal);
	// Desc: 设置验证码文本的随机大小
	// ====================================================
	capt.SetRangFontSize(&captcha.RangeVal{Min: 32, Max: 42})
	// ====================================================
	// Method: SetRangCheckTextLen(val *captcha.RangeVal);
	// Desc:设置验证码校验文本的随机长度的范围
	// ====================================================
	capt.SetRangCheckTextLen(&captcha.RangeVal{Min: 2, Max: 4})
	// ====================================================
	// Method: SetRangCheckFontSize(val *captcha.RangeVal);
	// Desc:设置验证码文本的随机大小
	// ====================================================
	capt.SetRangCheckFontSize(&captcha.RangeVal{Min: 24, Max: 30})
	// ====================================================
	// Method: SetTextRangFontColors(colors []string);
	// Desc: 设置验证码文本的随机十六进制颜色
	// ====================================================
	capt.SetTextRangFontColors([]string{
		"#1d3f84",
		"#3a6a1e",
		"#006600",
		"#005db9",
		"#aa002a",
		"#875400",
		"#6e3700",
		"#333333",
		"#660033",
	})
	// ====================================================
	// Method: SetImageFontAlpha(val float64);
	// Desc:设置验证码字体的透明度
	// ====================================================
	capt.SetImageFontAlpha(0.5)
	// ====================================================
	// Method: SetTextRangAnglePos(pos []*RangeVal);
	// Desc:设置验证码文本的角度
	// ====================================================
	capt.SetTextRangAnglePos([]*captcha.RangeVal{
		{1, 15},
		{15, 30},
		{30, 45},
		{315, 330},
		{330, 345},
		{345, 359},
	})
	// ====================================================
	// Method: SetImageFontDistort(val int);
	// Desc:设置验证码字体扭曲程度
	// ====================================================
	capt.SetImageFontDistort(captcha.ThumbBackgroundDistortLevel2)
	// ====================================================
	// Method: SetThumbBgColors(colors []string);
	// Desc: 设置缩略验证码背景的随机十六进制颜色
	// ====================================================
	capt.SetThumbBgColors([]string{
		"#1d3f84",
		"#3a6a1e",
	})
	// ====================================================
	// Method: SetThumbBackground(colors []string);
	// Desc:设置缩略验证码随机图像背景
	// ====================================================
	capt.SetThumbBackground([]string{
		path + "/public/upload/captcha/images/thumb/r1.jpg",
		path + "/public/upload/captcha/images/thumb/r2.jpg",
		path + "/public/upload/captcha/images/thumb/r3.jpg",
		path + "/public/upload/captcha/images/thumb/r4.jpg",
		path + "/public/upload/captcha/images/thumb/r5.jpg",
	})
	// ====================================================
	// Method: SetThumbBgDistort(val int);
	// Desc:设置缩略验证码的扭曲程度
	// ====================================================
	capt.SetThumbBgDistort(captcha.ThumbBackgroundDistortLevel2)
	// ====================================================
	// Method: SetThumbBgCirclesNum(val int);
	// Desc:设置验证码背景的圈点数
	// ====================================================
	capt.SetThumbBgCirclesNum(20)
	// ====================================================
	// Method: SetThumbBgSlimLineNum(val int);
	// Desc:设置验证码背景的线条数
	// ====================================================
	capt.SetThumbBgSlimLineNum(3)

	// ====================================================
	dots, b64, tb64, key, err := capt.Generate()
	if err != nil {
		return Captcha{}
	}
	redis, err := Conn()
	dot, _ := json.Marshal(dots)
	errSet := SetValue(redis, key, string(dot))
	if err == nil && errSet == nil {
		return Captcha{
			ImageBase64: b64,
			ThumbBase64: tb64,
			CaptchaKey:  key,
		}
	} else {
		return Captcha{}
	}
}
func Check(key string, dots string) (string, error) {
	if dots == "" && key == "" {
		return "check fail", errors.New("dots or key param is empty")
	}
	redis, err := Conn()
	if err == nil {
		cacheDots, err1 := GetValue(redis, key)
		if err1 == nil && len(cacheDots) > 0 {
			src := strings.Split(dots, ",")
			var dct map[int]captcha.CharDot
			if err2 := json.Unmarshal([]byte(cacheDots), &dct); err2 != nil {
				return "check fail", errors.New("illegal key")
			}
			chkRet := false
			if len(src) >= len(dct)*2 {
				chkRet = true
				for i, dot := range dct {
					j := i * 2
					k := i*2 + 1
					a, _ := strconv.Atoi(src[j])
					b, _ := strconv.Atoi(src[k])
					chkRet = checkDist(a, b, dot.Dx, dot.Dy, dot.Width, dot.Height)
					if !chkRet {
						break
					}
				}
			}
			if chkRet && (len(dct)*2) == len(src) {
				return "check success", nil
			} else {
				return "check fail", errors.New("check fail")
			}
		} else {
			return "check fail", err1
		}
	} else {
		return "check fail", err
	}
}

/**
 * @Description: Calculate the distance between two points
 * @param sx
 * @param sy
 * @param dx
 * @param dy
 * @param width
 * @param height
 * @return bool
 */
func checkDist(sx, sy, dx, dy, width int, height int) bool {
	return sx >= dx &&
		sx <= dx+width &&
		sy <= dy &&
		sy >= dy-height
}

type Captcha struct {
	ImageBase64 string `json:"image_base64"`
	ThumbBase64 string `json:"thumb_base64"`
	CaptchaKey  string `json:"captcha_key"`
}
